﻿// Necroz project team © <2015> <ArchLord2EMU>
// 
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
// 
// Author:Sagara
// Date:2015-09-24-21:57

using System.Collections.Concurrent;
using System.Net;
using System.Threading;
using AL2Game.Configs;
using AL2Game.Interfaces;
using ArchLord2Commons.Models;
using ArchLord2Commons.Network.Pipe;
using CM.Framework.Network.RMI;
using NLog;

namespace AL2Game.Services
{
    class LoginServicePipeService : ILsService
    {
        private static readonly Logger Log = LogManager.GetLogger(typeof(LoginServicePipeService).Name);

        public static readonly RMIPipe<IRMILoginBridge> Client = new RMIPipe<IRMILoginBridge>(new LoginServicePipeService(), 2000);

        public static readonly ConcurrentDictionary<int, AccountData> Online = new ConcurrentDictionary<int, AccountData>();
         
        private static readonly object _lClient = new object();
        public void Initilize()
        {
            Client.OnDisconnected += () =>
            {
                Log.Warn("Connection with LoginServer was dropped! Trying to reconnect..");

                ConnectLoop();
            };

            ConnectLoop();
        }

        public void Release()
        {
           Client.Dispose();
        }
        private static void ConnectLoop()
        {
            Client.Connect(new IPEndPoint(IPAddress.Parse(NetworkCfg.Default.PipeHost), NetworkCfg.Default.PipePort),
                res =>
                {
                    if (res)
                    {
                        Client.RemoteService.SetRealmInfo(GameServerCfg.Default.GameserverId, GameServerCfg.Default.GameserverName);
                        Log.Info("Connected to LoginServer on '{0}:{1}'", NetworkCfg.Default.PipeHost,
                            NetworkCfg.Default.PipePort);
                    }
                    else
                    {
                        Log.Warn("Can't connect to LoginServer on '{0}:{1}'. Retrying...", NetworkCfg.Default.PipeHost,
                            NetworkCfg.Default.PipePort);
                        Thread.Sleep(2000);
                        ConnectLoop();
                    }
                });
        }

        public void DisconnectAccountOnLogin(int accountId)
        {
            lock(_lClient)
                Client.RemoteService.NotifyAccountDisconnected(accountId);
        }

        public void DisconnectAccount(int accountId)
        {
            AccountData toOut;

            Online.TryRemove(accountId, out toOut);
        }

        public bool IsConnected(int accountId)
        {
            return Online.ContainsKey(accountId);
        }

        public GsInfo GetRealmInfo(int accountId)
        {
            byte charactersOnAccount = 0; //todo

            var gameServerInfo = new GsInfo(
                GameServerCfg.Default.GameserverId, 
                GameServerCfg.Default.GameserverName, 
                charactersOnAccount, 
                NetworkCfg.Default.GameServerIp);

            return gameServerInfo;
        }

        public AccountData AccountInfo(string token)
        {
            lock (_lClient)
                return Client.RemoteService.GetAccountInfo(token, GameServerCfg.Default.GameserverId);
        }
    }
}
